/*
   Copyright (c) 2005 Lucas Mello Schnorr <schnorr@gmail.com>
   
   This file is part of DIMVisual.
   
   DIMVisual is free software; you can redistribute it and/or modify it under
   the terms of the GNU Lesser General Public License as published by the
   Free Software Foundation; either version 2 of the License, or (at your
   option) any later version.
   
   DIMVisual is distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   for more details.
   
   You should have received a copy of the GNU Lesser General Public License
   along with DIMVisual; if not, write to the Free Software Foundation, Inc.,
   59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include "MPIRASTROConverter.h"

static AllToOne *reduce;
static int size = -1;

@implementation MPIRASTROConverter (Reduce)
- (id) convertEventReduce: (GEvent *) event
{
	NSMutableArray *ret = nil;
	NSString *container;
//	int type;
	int i;

	GFields *f = [event fields];

	NSString *machine, *thread, *node, *identifier, *time;
	NSString *int32AtIndex0, *int32AtIndex1, *int32AtIndex2;
	NSString *stringAtIndex0;

        machine = [[f fieldWithSimpleStringKey:@"machine"] description];
        thread = [[f fieldWithSimpleStringKey: @"thread"] description];
        node = [[f fieldWithSimpleStringKey: @"node"] description];
        identifier = [[event identifier] description];
        time = [[event timestamp] description];
        int32AtIndex0 = [[f fieldWithSimpleStringKey: @"uint32-0"] description];
        int32AtIndex1 = [[f fieldWithSimpleStringKey: @"uint32-1"] description];
        int32AtIndex2 = [[f fieldWithSimpleStringKey: @"uint32-2"] description];
        stringAtIndex0 = [[f fieldWithSimpleStringKey: @"string-0"] description];

	if (reduce == nil){
		reduce = [[AllToOne alloc] init];
	}
	if (allreduce == nil){
		allreduce = [[NSMutableArray alloc] init];
	}
	
	ret = [[NSMutableArray alloc] init];

	container = [provider identifierForEntity: 
		[NSArray arrayWithObjects: @"Machine", @"Thread", nil]
				ids:
		[NSArray arrayWithObjects: machine, thread, nil]];

	if (container == nil){
		[ret release];
		return nil;
	}
	
	int etype = atoi ([identifier cString]);

/*******************************************************************************
          MPI_ALLREDUCE
*******************************************************************************/
	if (etype == MPI_ALLREDUCE_IN){
		if (size == -1){
			size = atoi([int32AtIndex2 cString]);
			for (i = 0; i < size; i++){
				AllToOne *reduce = [[AllToOne alloc] init];
				[allreduce addObject: reduce];
				[reduce release];
			}
		}
		for (i = 0; i < size; i++){
			[[allreduce objectAtIndex:i] memberEntering: container
				andEventNode: node
				andEventTime: time
				andRootNode: [NSString stringWithFormat:@"%d",i]
				andCommSize: int32AtIndex2
				andMembersId: stringAtIndex0];
		}
		[ret addObject: [self addPajeSetState: @"MPI_ALLREDUCE" time: time container: container]];


	}else if (etype == MPI_ALLREDUCE_OUT){
		for (i = 0; i < size; i++){
			[ret addObjectsFromArray:
				[[allreduce objectAtIndex:i]
					memberExiting: container
					andEventTime: time
					andOperationName: @"allreduce"
					andRootNode: nil
					andMembersId: nil
					andProvider: provider]];
		}
		[ret addObject: [self addPajeSetState: @"running" time: time container: container]];

		
/*******************************************************************************
          MPI_REDUCE_SCATTER
*******************************************************************************/
	}else if (etype == MPI_REDUCE_SCATTER_IN){
		[ret addObject: [self addPajeSetState: @"MPI_REDUCE_SCATTER" time: time container: container]];
	}else if ( etype == MPI_REDUCE_SCATTER_OUT){
		[ret addObject: [self addPajeSetState: @"running" time: time container: container]];

/*******************************************************************************
          MPI_REDUCE
*******************************************************************************/
	}else if (etype == MPI_REDUCE_IN){
		[reduce memberEntering: container
			andEventNode: node
			andEventTime: time
			andRootNode: int32AtIndex1
			andCommSize: int32AtIndex2
			andMembersId: stringAtIndex0];
		[ret addObject: [self addPajeSetState: @"MPI_REDUCE" time: time container: container]];


	}else if (etype == MPI_REDUCE_OUT){
		NSLog (@"f = %@", f);
		[ret addObjectsFromArray: [reduce memberExiting: container
			andEventTime: time
			andOperationName: @"reduce"
			andRootNode: nil
			andMembersId: nil
			andProvider: provider]];
		[ret addObject: [self addPajeSetState: @"running" time: time container: container]];
	}


	[ret autorelease];
	return ret;
}
@end
